package resilienceManager.qmul.gemom;


import java.awt.*;
import java.awt.event.*;
import java.util.Enumeration;

import javax.swing.JTabbedPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

/**
 * The class ControlPanel controls the threads in the monitor demonstration.
 * 
 * COPYRIGHT DISCLAIMER
 * Synopsis: All the source codes presented in this document are intellectual
 * properties of Queen Mary, University of London.
 * 
 * @year 2010
 * @author Peng Jiang, John Bigham, Jiayi Wu, Jinfu Wang------------QMUL
 * @version 1.0 
 */

public class ThreadControlPanel extends Panel implements ActionListener
{
	/**
	 * The threads to control.
	 */
	private starThread[] threads;


	/**
	 * the list of Gbroker
	 * */

	private Gbroker[] glist;

	/**
	 * The thread choice.
	 */
	private Choice threadChoice;

	/**
	 * The state field.
	 */
	private TextField stateField;

	/**
	 * The start button.
	 */
	private Button startButton;

	/**
	 * The stop button.
	 */
	private Button resumeButton;

	/**
	 * The pause button.
	 */
	private Button pauseButton;

	/**
	 * The syn button.
	 */
	private Button synButton;
	
	
	/**
	 * The show search tree button
	 * */
	private Button searchButton;


	/**
	 * The show result button
	 * */
	private Button treeButton;
	
	/**
	 * The JTree used for thread seerach
	 * */
	private JTree tree;
	
	/**
	 * The JTabbedPane
	 * */
	private JTabbedPane tabbedpane;


	/**
	 * Creates a ControlPanel object.
	 * @param threads the threads to control
	 */
	public ThreadControlPanel( starThread[] threads, Gbroker[] list)
	{
		this.threads = threads;
		GridBagLayout layout = new GridBagLayout();
		setLayout( layout );
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.anchor = GridBagConstraints.WEST;
		gbc.fill = GridBagConstraints.HORIZONTAL;

		// set the Gbroker
		glist=list;

		// add thread label
		Label threadLabel = new Label( "Gbroker:" );
		gbc.gridx = 0; gbc.gridy = 0;
		gbc.insets = new Insets( 10, 20, 0, 0 );
		layout.setConstraints( threadLabel, gbc );
		add( threadLabel );

		// add thread choice
		threadChoice = new Choice();
		for ( int i = 0; i < threads.length; i++ )
		{
			int id=glist[i].getID();
			threadChoice.add( id + "" );
		}
		gbc.gridx = 1; gbc.gridy = 0;
		gbc.insets = new Insets( 10, 0, 0, 10 );
		layout.setConstraints( threadChoice, gbc );
		add( threadChoice );

		// add state label
		Label stateLabel = new Label( "State:" );
		gbc.gridx = 0; gbc.gridy = 1;
		gbc.insets = new Insets( 5, 20, 20, 0 );
		layout.setConstraints( stateLabel, gbc );
		add( stateLabel );

		// add state text
		stateField = new TextField( 5 );
		stateField.setEditable( false );
		gbc.gridx = 1; gbc.gridy = 1;
		gbc.insets = new Insets( 5, 0, 20, 10 );
		layout.setConstraints( stateField, gbc );
		add( stateField );

		// add start button
		startButton = new Button( "Start Search" );
		gbc.gridx = 2; gbc.gridy = 0;
		gbc.gridwidth = 1;
		gbc.insets = new Insets( 10, 10, 0, 10 );
		layout.setConstraints( startButton, gbc );
		add( startButton );
		startButton.addActionListener( this );

		// add stop button
		resumeButton = new Button( "Resume Search" );
		gbc.gridx = 2; gbc.gridy = 1;
		gbc.insets = new Insets( 5, 10, 20, 10 );
		layout.setConstraints( resumeButton, gbc );
		add( resumeButton );
		resumeButton.addActionListener( this );

		// add enter monitor button
		synButton = new Button( "star Sync" );
		gbc.gridx = 3; gbc.gridy = 0;
		gbc.insets = new Insets( 10, 10, 0, 10 );
		layout.setConstraints( synButton, gbc );
		add( synButton );
		synButton.addActionListener( this );

		// add leave monitor button
		pauseButton = new Button( "Pause Search" );
		gbc.gridx = 3; gbc.gridy = 1;
		gbc.insets = new Insets( 5, 10, 20, 10 );
		layout.setConstraints( pauseButton, gbc );
		add( pauseButton );
		pauseButton.addActionListener( this );
		
		// add tree show button
		searchButton = new Button("Search Tree");
		gbc.gridx = 4; gbc.gridy = 0;
        gbc.insets = new Insets( 10, 10, 0, 20 );
        layout.setConstraints( searchButton, gbc );
        add( searchButton );
        searchButton.addActionListener( this );
		
		// add tree show button
		treeButton = new Button("Search Result");
		gbc.gridx = 4; gbc.gridy = 1;
        gbc.insets = new Insets( 5, 10, 20, 20 );
        layout.setConstraints( treeButton, gbc );
        add( treeButton );
        treeButton.addActionListener( this );
        
        


	}

	/**
	 * Paints the panel.
	 * @param g the graphics context to use
	 */
	public void paint( Graphics g )
	{
		// disable buttons
		Component[] comp = getComponents();
		for ( int i = 0; i < comp.length; i++ )
			if ( comp[i] instanceof Button )
				comp[i].setEnabled( false );

		// update state field and enable buttons
		int i = threadChoice.getSelectedIndex();
		switch ( threads[i].getcurrentState() ) {
		case starThread.CREATED:
			stateField.setText( "Created" );
			startButton.setEnabled( true );
			break;
		case starThread.RUNNING:
			stateField.setText( "Running" );
			startButton.setEnabled(false);
			resumeButton.setEnabled( false );
			pauseButton.setEnabled( true );
			synButton.setEnabled(true);
			break;
		case starThread.SYNCHRONIZATION:
			stateField.setText( "Sync" );
			break;
		case starThread.PAUSE:
			stateField.setText( "Pause" );
			resumeButton.setEnabled( true );
			treeButton.setEnabled(true);
			searchButton.setEnabled(true);
			break;
		case starThread.STOP:
			stateField.setText( "Finsh" );
			treeButton.setEnabled(true);
			searchButton.setEnabled(true);
			break;
		}
		
	}

	/**
	 * Handles an action event.
	 * @param event the action event
	 */
	public void actionPerformed( ActionEvent event )
	{
		Button button = (Button)event.getSource();
		int i = threadChoice.getSelectedIndex();
		if ( button.equals( startButton ) )
			try { threads[i].start(); }
		catch ( IllegalThreadStateException e ) {}
		else if ( button.equals( resumeButton ) )
		{ 
			threads[i].resumeThread();
			try{threads[i].resume();} catch(SecurityException e){}
		}
		else if ( button.equals( synButton ) )
		{ 
			threads[i].synThread(threads);

		}
		else if ( button.equals( pauseButton ) )
		{ 
			threads[i].pauseThread();
			try {threads[i].suspend();}catch(SecurityException e){}
		}else if (button.equals(treeButton))
		{
			DefaultMutableTreeNode root= threads[i].SearchTree();
			DefaultTreeModel tmodel=new DefaultTreeModel(root);
			tree.setModel(tmodel);
			
			expandAll(tree, new TreePath(root),true);
			
			tree.getParent().repaint();
			
			tabbedpane.setSelectedIndex(7);
		}else if ( button.equals(searchButton))
		{
			DefaultMutableTreeNode root= threads[i].getBidTree();
			DefaultTreeModel tmodel=new DefaultTreeModel(root);
			tree.setModel(tmodel);
			
			expandAll(tree, new TreePath(root),true);
			
			tree.getParent().repaint();
			
			tabbedpane.setSelectedIndex(7);
		}
		


	}

	/**
	 * all start action 
	 * 
	 * */
	public void allStart()
	{
		for(int i=0; i<threads.length; i++)
		{
			threads[i].start();

		}
	}

	/**
	 * all stop action
	 * */
	public void allStop()
	{
		for(int i=0; i<threads.length; i++)
		{
			threads[i].terminate();
		}

	}

	/**
	 * set the 
	 * @param thread tree  the JTree used for the search result 
	 * */
	public void setTree(JTree t, JTabbedPane tp)
	{
		tree=t;
		
		tabbedpane=tp;
	}
	
	// expand all path for a JTree
	private void expandAll(JTree tree, TreePath parent, boolean expand) {
		// Traverse children
		DefaultMutableTreeNode node = (DefaultMutableTreeNode)parent.getLastPathComponent();
		if (node.getChildCount() >= 0) {
			for (Enumeration e=node.children(); e.hasMoreElements(); ) {
				DefaultMutableTreeNode n = (DefaultMutableTreeNode)e.nextElement();
				TreePath path = parent.pathByAddingChild(n);
				expandAll(tree, path, expand);
			}
		}

		// Expansion or collapse must be done bottom-up
		if (expand) {
			tree.expandPath(parent);
		} else {
			tree.collapsePath(parent);
		}
	}

}

